﻿using Skybot.Logs.Broken;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace InCom.Forward.Core
{
     public class 示例使用类
    {




        #region 连接故障补传
        //1.当数据连接错误时进入  补传模式 将 ConnBrokenIsUserd=true;
        //2.向故障日志中写入数据 WriteBroken
        //3.当联接恢复后.启用 ReadBroken

        /// <summary>
        /// 当前是否进入补传模式
        /// </summary>
        public bool ConnBrokenIsUserd { get; set; }

        /// <summary>
        /// 网络故障后补传功能
        /// </summary>
        protected ConnBrokenSupplements brokenLog = null;

        /// <summary>
        /// 写入多少条数据到Broken日志中
        /// </summary>
        /// <param name="num">默认一次写入50000条记录</param>
        public void WriteBroken(int num = 50000)
        {
            ConnBrokenIsUserd = true;

            //写入字到故障文件中
            if (!brokenLog.Write(System.Text.Encoding.UTF8.GetBytes("故障数据")))
            {
                //对写入失败的数据进行处理,重新增加了写入队列中,这里可能会引起顺序错误问题.
                throw new NullReferenceException("写入失败的异常");
            }


        }

        /// <summary>
        /// 读取日志数据
        /// </summary>
        public void ReadBroken()
        {
            try
            {
                if (ConnBrokenIsUserd)
                {
                    int filenum = 0;
                    Console.WriteLine("开始读取转发故障文件------------:{0}", brokenLog.BrokenDir);
                    while (brokenLog.ReadBroken(BrokenSendMethod, out filenum))
                    {
                        Console.WriteLine("故障目录{0},还有文件个数:{1}", brokenLog.BrokenDir, filenum);
                    }
                    //表示所有文件已经全部补发完了
                    if (brokenLog.BrokenFilesNumber < 1)
                    {
                        //故障模式结束
                        ConnBrokenIsUserd = false;
                    }
                }
            }
            catch (Exception ex)
            {
                inCom.Logs.LogProvider.Create().Write(inCom.Logs.EventType.Error, string.Format("读取故障数据时出现异常:{0}", ex));

            }
        }
        /// <summary>
        /// 故障数据发送方法
        /// </summary>
        /// <param name="arr">需要发送的数据</param>
        protected bool BrokenSendMethod(byte[] arr)
        {

            //发送数据
            return Send(arr);


            //返回false 将会停止发送故障数据
            return false;
        }

        /// <summary>
        /// 发送数据
        /// </summary>
        /// <param name="arr"></param>
        private bool Send(byte[] arr)
        {
            return arr.Length % 2 == 1;
        }


        #endregion




        object forwardDataQueue;
        /// <summary>
        /// 开始运行
        /// </summary>
        public void Start(int targetDbType, IPEndPoint ep)
        {
            //需要定议初始化
            //使用此方法可以防止多次初始化
            System.Threading.LazyInitializer.EnsureInitialized(ref forwardDataQueue, () =>
            {
                forwardDataQueue = new object();

                #region 网络故障后的补传

                //默认30分钟一个文件
                brokenLog = new ConnBrokenSupplements() { MinuteInterval = 30 };
                string UserID = "测试用户名";
                //设置初始化目录
                brokenLog.Init(UserID + "-" + ep.ToString().Replace(":", " "));
                //默认开始补传,因为有可能程序异常关闭.需要启动后补传数据
                ConnBrokenIsUserd = true;
                #endregion



                return forwardDataQueue;
            });

        }



        #region 发送到第三方

        /// <summary>
        /// 循环发送到第三方
        /// </summary>
        public void CycleSendToTarget()
        {
            while (true)
            {
                //单个协议体发送
                SingleSendToTarget();
            }
        }




        #region 单协议体发送

        /// <summary>
        /// 单包向第三方目标发送数据
        /// </summary>
        public void SingleSendToTarget()
        {


            if (是不是故障了)
            {

                #region 故障数据处理
                //正处于故障模式
                if (ConnBrokenIsUserd)
                {
                    //读取故障数据并且发送到指定端口
                    ReadBroken();
                }

                #endregion

            }
            else
            {
                #region 故障数据处理
                //将故障数据写入到日志中
                WriteBroken();
                #endregion

                //如果socket 异常时暂停5毫秒.
                System.Threading.Thread.Sleep(5);
            }

        }

        #endregion



        #endregion


        public bool 是不是故障了 { get; set; }
    }



}

